home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
lpmac1.arc
/
MACROS.DOC
< prev
next >
Wrap
Text File
|
1987-03-03
|
25KB
|
643 lines
Documentation for MACROS.MLB Page 1
TABLE OF CONTENTS
INTRODUCTION . . . . . . . . . . . . . . . . . . . . . . . . 2
CONVENTIONS, OPENING MACROS AND CLOSING MACROS . . . . . . . 3
LISTING CONTROL . . . . . . . . . . . . . . . . . . . . 3
OUT_UNNECESSARY_LONG_COMMENTS - Closing summary macro . 3
BLANK MACRO ARGUMENTS . . . . . . . . . . . . . . . . . 3
CONVENTIONS IN THIS DOCUMENTATION . . . . . . . . . . . 4
A STRATEGY TO MINIMIZE THE NUMBER OF LONG JUMPS . . . . . . 5
JUMPS TO EXPLICIT LABELS . . . . . . . . . . . . . . . . . . 6
GENERAL . . . . . . . . . . . . . . . . . . . . . . . . 6
LJMP TARGET_LABEL, LONG - Unconditional jump to
TARGET_LABEL. . . . . . . . . . . . . . . . . . . 6
LCJMP CONDITION-1, TARGET_LABEL, LONG - Conditional
jump to TARGET_LABEL. . . . . . . . . . . . . . . 6
LJCXZ TARGET_LABEL, LONG - Jump to TARGET_LABEL if
register CX is zero. . . . . . . . . . . . . . . . 6
LLOOP CONDITION-3, TARGET_LABEL, LONG - Conditional and
unconditional loops. . . . . . . . . . . . . . . . 6
STRUCTURED MACROS . . . . . . . . . . . . . . . . . . . . . 7
GENERAL . . . . . . . . . . . . . . . . . . . . . . . . 7
Jump to the beginning or the end of an "enclosing
block" . . . . . . . . . . . . . . . . . . . . . . 8
BEGIN and END . . . . . . . . . . . . . . . . . . . . . 9
IF and IF - ELSE with one condition . . . . . . . . . . 9
IF and IF - ELSE with multiple AND conditions . . . . . 10
Repetition for a count . . . . . . . . . . . . . . . . 11
WHILE . . . . . . . . . . . . . . . . . . . . . . . . . 12
REPEAT UNTIL . . . . . . . . . . . . . . . . . . . . . 12
REPEAT FOREVER . . . . . . . . . . . . . . . . . . . . 12
OTHER MACROS . . . . . . . . . . . . . . . . . . . . . . . . 13
Multiple PUSH and POP . . . . . . . . . . . . . . . . . 13
Show the state of the Zero Flag in AL . . . . . . . . . 13
NOTZ - Toggle the Zero Flag . . . . . . . . . . . . . . 13
Call procedures which use a string whose OFFSET is in
either BX or DX . . . . . . . . . . . . . . . . . 13
Call a procedure which uses a File Control Block . . . 14
Documentation for MACROS.MLB Page 2
I. INTRODUCTION
I based this collection of macros for MicroSoft MASM on
MACROS.MLB in the public domain file HERSHMAC.ARC, which Mark
Hersey of Hersey Micro Consulting, Inc. wrote. I made enough
changes so that I can not claim that his work created any
problems you might find with it.
HERSHMAC.ARC also includes the following files which define
symbolic constants:
CHARS.MLB contains constant declarations for ASCII
characters.
I8086.MLB contains constant declarations which are for
use with an 8086 assembler.
MSDOS.MLB contains constant declarations which are for
use with Seattle Computer Products MS-DOS operating system.
They seem useable for Microsoft's PC-DOS also.
I have tried to be sure that MACROS.MLB and these three files do
not depend on one another. I have included them in this ARChive.
Michael Abrash's article "Conditional-jump Macros" in the
February, 1987 issue of "PC Tech Journal" inspired the macros
which begin with the letter L and give various forms of jump and
loop instructions.
Since I am placing these macros in the public domain, I am
not responsible for any bad things which they might do.
Lew Paper
10:53 am on 3/1/87
Documentation for MACROS.MLB Page 3
II. CONVENTIONS, OPENING MACROS AND CLOSING MACROS
A. LISTING CONTROL
MASM allows three kinds of listing for macro expansions.
.LALL lists code and ";" comments; .XALL lists code only; .SALL
surpresses all listing. The default is .XALL.
MACROS.MLB uses the macro variable MACRO_EXPANSION_CONTROL
to specify which level you want. If it is not defined, it
assumes .XALL, which is consistent with the MASM default. Its
definitions are:
0 for .XALL (list code only)
1 for .SALL (surpress all listing)
2 for .LALL (list code and comments).
Any other value also gives .XALL.
The macro SET_MACRO_EXPANSION actually sets MASM's listing
control according to to the value in MACRO_EXPANSION_CONTROL.
As discussed below, a long jump to a forward label which
could be short will generate a comment. MACROS.MLB needs
something like MACRO_EXPANSION_CONTROL to reset itself
afterwards.
B. OUT_UNNECESSARY_LONG_COMMENTS - Closing summary macro
Use the macro OUT_UNNECESSARY_LONG_COMMENTS, which has no
arguments, at the end of any file which uses any of the macros
described in Section III, JUMPS TO EXPLICIT LABELS or Section IV,
STRCTURED MACROS with a LONG argument. It will add a comment if
there are any unnecessary long forward jumps and also print a
message to that effect on the screen. It does nothing if there
are none.
Strictly speaking, you only need to use
OUT_UNNECESSARY_LONG_COMMENTS if you have a forward long jump.
Rather than worry about whether a structured macro is forward or
backward, it is easier to use it in any case where it might come
into play.
C. BLANK MACRO ARGUMENTS
Indicate that all arguments of a macro are blank by not
entering a macro list. Indicate that the last argument of a
macro is blank by ending the argument list with the last
non-blank argument. Indicate that the first argument of a macro
is blank by starting the macro list with a comma. Indicate that
an internal argument of a macro is blank by entering just a comma
following the preceding comma.
Documentation for MACROS.MLB Page 4
CONVENTIONS, OPENING MACROS AND CLOSING MACROS (Continued)
D. CONVENTIONS IN THIS DOCUMENTATION
CONDITION-1 is a completion to any conditional jump J
instruction except JCXZ. Its legal values are:
A, AE, B, BE, C, E, G, GE, L, LE, NA, NAE, NB, NBE, NC,
NE, NG, NGE, NL, NLE, NO, NP, NS, NZ, O, P, PE, PO, S, Z.
CONDITION-2 is a completion to any condition jump J
instruction which tests flags affected by an OR instruction
except JCXZ. The values for which it gives a choice are:
BE, E, G, GE, L, LE, NA, NE, NG, NGE, NL, NLE, NP, NS,
NZ, P, PE, PO, S, Z.
It is always true, so probably not useful, for:
A, AE, NB, NBE, NC, NO.
It is always false, so probably not useful, for:
B, C, O, NAE.
CONDITION-3 is a completion to any LOOP instruction. Its
legal values are:
blank, E, NE, NZ, Z.
VAR1, CONDITION, VAR2 has two meanings. If VAR2 is blank,
it means, "AND VAR1, VAR1", then jump on CONDITION-2. Since the
8086 does not allow "AND mem, mem", this option only works if
VAR1 is a register. If VAR2 is not blank, it means,
"CMP VAR1, VAR2", then jump on CONDITION-1. Since the 8086 does
not allow "CMP mem1, mem2", this option requires that either VAR1
or VAR2 be either a register or an immediate variable. Most of
the macros have a form which jumps on a condition which is
already set. In those cases, you are free to set it by any
operation you want.
LONG forces MASM to compile a long forward jump if it is not
blank. It is always the last argument. Anything in this
position will do, but the word "long" could clarify your meaning.
Incidentally, MACROS.MLB ignores LONG for a backward jump.
Documentation for MACROS.MLB Page 5
III. A STRATEGY TO MINIMIZE THE NUMBER OF LONG JUMPS
MASM can determine whether a backward jump is long or short
on pass 1, but it can't do the same thing for forward jumps. The
LONG argument is the way the macros below respond to this
problem.
One general strategy which you coud follow to assure
yourself that there are no unnecessary long jumps is:
Compile with no LONG arguments.
If there are any "Relative jump out of range"
error messages, add a LONG argument to those macros and
compile again.
Repeat the last step until there are no "Relative
jump out of range" error messages.
Since each LONG adds some bytes, it is possible that adding
a LONG argument will spread out another forward jump so it must
be long. You can cook up some very intertwined examples which
would take many cycles to clear up, but usually there shouldn't
be too many recyclings.
If you are sure that a forward jump will exceed 127 bytes,
you could use a LONG argument immediately. If you are wrong, you
will get a comment which tells you that that particular jump
doesn't need to be long. If this happens, I suggest that you use
the pure general strategy which I outlined above.
Documentation for MACROS.MLB Page 6
IV. JUMPS TO EXPLICIT LABELS
A. GENERAL
MASM can determine whether a backward jump is long or short
on pass 1. It can't do the same thing for a forward jump, but it
can tell on pass 2 if a long forward jump could have been short.
These macros take advantage of those abilities.
Each of them jump or loop to the argument target_label. For
backward jumps, each of them either issues a short jump or else
one or more instructions which give the same conditional effect
if any and issue a long jump.
For forward jumps, they all use the variable LONG, which I
described in Section II-D above. MASM will flag short forward
jumps which should have been long as an error 53, "Relative jump
out of range." Each of these macros write a comment, "******
This jump doesn't need to be LONG ******" for a long forward jump
which could have been short.
See Section III above for a strategy which minimizes the
number of long jumps.
B. LJMP TARGET_LABEL, LONG - Unconditional jump to TARGET_LABEL.
C. LCJMP CONDITION-1, TARGET_LABEL, LONG - Conditional jump to
TARGET_LABEL.
CONDITION-1 is the conditional part of any J? operation
except JCXZ. See Section II-D above for a complete list.
D. LJCXZ TARGET_LABEL, LONG - Jump to TARGET_LABEL if register
CX is zero.
E. LLOOP CONDITION-3, TARGET_LABEL, LONG - Conditional and
unconditional loops.
Use "LLOOP ,TARGET_LABEL, LONG" for an unconditional loop.
See Section II-C for a discussion of blank macro arguments.
Otherwise, E, NE, NZ, Z are legal values for CONDITION-3.
Documentation for MACROS.MLB Page 7
V. STRUCTURED MACROS
A. GENERAL
Structured macros are combinations of macros which produce
the effects of structured programming. They generate their own
labels, which have the form L?n, where n is a number which is
more or less sequential. They can be nested almost indefinitely.
They use all of the long and short features of jumps to
explicit labels discussed in Section III-A above. If a component
macro includes a forward jump, its arguments will terminate with
LONG. See Section III above for a strategy which minimizes the
number of long jumps.
See Section II-D for descriptions of arguments not
explicitly described with the structured macro.
The list of structured macros below is probably not
complete. You can use the source code to build other
combinations to fit your particular needs.
Documentation for MACROS.MLB Page 8
STRUCTURED MACROS (Continued)
B. Jump to the beginning or the end of an "enclosing block"
I will define the term "enclosing block" to mean a pair of
macros which establish internal labels at the start of the first
one and after the second one. Several of the macro combinations
discussed below form enclosing blocks. The following macros will
jump to the beginning or past the end of any of them:
XNEXT LONG ; Unconditionally jump to the
; beginning of the block
XCNEXT VAR1, CONDITION, VAR2, LONG
; Set condition then conditionally
; jump to the beginning of the
; block
XCNEXTC CONDITION-1, LONG
; Jump to the beginning of the
; block based on the condition when
; you invoke the macro
XEXIT LONG ; Unconditionally jump to beyond
; the end of the block
XCEXIT VAR1, CONDITION, VAR2, LONG
; Set condition then conditionally
; jump to beyond the end of the
; block
XCEXITC CONDITION-1 LONG
; Jump to beyond the end of the
; block based on the condition when
; you invoke the macro
You can use these macros outside of an enclosing block. The
NEXT macros will look for the internal label with the next
sequential number, and the EXIT macros will look for the internal
label with the current sequential number plus 2. There are
enough possibilities so that their effect is somewhat
unpredicable. I suggest a jump to an explicit label instead.
If these macros are used inside of an enclosing block,
XEXIT, XCEXIT and XCEXITC include forward jumps.
Each section will say whether its macros form an enclosing
block.
Documentation for MACROS.MLB Page 9
STRUCTURED MACROS (Continued)
C. BEGIN and END
XBEGIN
body
XEND
BEGIN and END form an enclosing block with no other effects.
D. IF and IF - ELSE with one condition
XIF VAR1, CONDITION, VAR2, LONG
body
XENDIF
If you want to set CONDITION-1 before you invoke XIF,
replace the XIF line with
XIFC CONDITION-1, LONG
Each of these forms allows an optional ELSE clause. For
example, the first form becomes:
XIF VAR1, CONDITION, VAR2, LONG
body-1
XELSE LONG
body-2
XENDIF
XIF, XIFC and XELSE each include forward jumps.
XIF and XENDIF form an enclosing block as long as there is
no XELSE between them. If there is an XELSE between them, they
do not form and enclosing block. For this reason, it is probably
safer to use XBEGIN and XEND around body-1 and/or body-2 if you
want any form of XNEXT or XEXIT.
Documentation for MACROS.MLB Page 10
STRUCTURED MACROS (Continued)
E. IF and IF - ELSE with multiple AND conditions
XIF VAR1, CONDITION, VAR2, LONG
XANDIF VAR1, CONDITION, VAR2, LONG
; The two invocations should have
; at least one of VAR1, CONDITION
; and VAR2 different to be useful.
body
XENDIF
You must first use exactly one XIF. You can then use more
than one XANDIF.
You can use both XIFC and XELSE as above in this form. In
addition, you can set CONDITION-1 for an XANDIF and replace it
with
XANDIFC CONDITION-1, LONG
XANDIF and XANDIFC each include forward jumps.
XIF or XIFC and XENDIF form an enclosing block as long as
there is no XELSE between them. If there is an XELSE between
them, they do not form and enclosing block. For this reason, it
is probably safer to use XBEGIN and XEND around body-1 and/or
body-2 if you want any form of XNEXT or XEXIT.
Documentation for MACROS.MLB Page 11
STRUCTURED MACROS (Continued)
F. Repetition for a count
Enter with CX set to the maximum number of times to repeat.
XFOR NOZERO, LONG
; If NOZERO is blank, skip the body
; of the loop if CX starts as zero.
; If it exists, always repeat at
; least once.
body
XDEC CONDITION-3
; End of loop
The value of NOZERO doesn't matter. For documentation, you
might consider using nozero.
LONG is only useful if NOZERO is blank. The three useful
configurations of the FOR line are:
FOR
FOR nozero
FOR , long
CONDITION-3 can be blank for an unconditional loop or E, NZ,
NE or Z for a conditional loop. See Section II-D for more
information on CONDITION-3.
If NOZERO is blank, XFOR contains a forward jump. If it is
not blank, XFOR does not contain a forward jump.
XFOR and XDEC form an enclosing block. XNEXT does not
change the number of repetitions. If you want to bypass part of
the processing for this repetition but keep on counting, enclose
body with XBEGIN and XEND and then use XEXIT.
Documentation for MACROS.MLB Page 12
STRUCTURED MACROS (Continued)
G. WHILE
XWHILE VAR1, CONDITION, VAR2, LONG
; Terminate loop if CONDITION-1
body
XENDLP ; End this pass through the loop
If you want to initialize CONDITION-1 before entering and
set it in body for the next pass through the loop, replace the
XWHILE line with
XWHILEC CONDITION-1, LONG
; Terminate loop if CONDTION-1
XEXIT and XEXITC include forward jumps.
XWHILE or XWHILEC and XENDLP form an enclosing block.
H. REPEAT UNTIL
XREPEAT ; Start of loop
body
XUNTIL VAR1, CONDITION, VAR2
; End this pass through the loop
If you want to set CONDITION-1 in body, replace the XUNTIL
line with
XUNTILC CONDITION-1 ; End this pass through the loop
XREPEAT and XUNTIL or XUNTILC form an enclosing block.
XNEXT does not test CONDITION-1. If you want to bypass part of
the processing for this repetition but still test, enclose body
with XBEGIN and XEND and then use XEXIT.
I. REPEAT FOREVER
XLOOP
body
XENDLP
body should include some form of XEXIT.
XLOOP and XENDLP form an enclosing block.
NOTE: XLOOP is a synonym for XREPEAT.
Documentation for MACROS.MLB Page 13
VI. OTHER MACROS
A. Multiple PUSH and POP
PUSH_REGISTER <REGISTER LIST> pushes the list of registers
contained in REGISTER LIST on the program stack and saves what it
has done for POP_REGISTER.
POP_REGISTER pops the registers saved by PUSH_REGISTER in
the proper order.
PUSHM <LIST> pushes the registers and memory locations
contained in LIST on the program stack in the same order as LIST.
POPM <LIST> pops the registers and memory locations
contained in LIST from the program stack in the same order as
LIST. If it is used with PUSHM, the two LIST's should be in
reversed order.
The angle brackets in PUSH_REGISTER, PUSHM and POPM are
required.
B. Show the state of the Zero Flag in AL
GETZ sets AL to TRUE if the Zero Flag is set and to FALSE if
it is not set.
GETNZ sets AL to TRUE if the Zero Flag is not set and to
FALSE if it is set.
C. NOTZ - Toggle the Zero Flag
D. Call procedures which use a string whose OFFSET is in either
BX or DX
CALLSTR ROUTINE, STRING
where
ROUTINE is the name of the procedure to call.
STRING is the name of a string whose OFFSET should go
into register DX.
GETCALL ROUTINE, STRING
where
ROUTINE is the name of the procedure to call.
STRING is the name of a string whose OFFSET should go
into register BX.
Documentation for MACROS.MLB Page 14
OTHER MACROS (Continued)
E. Call a procedure which uses a File Control Block
FCBCALL ROUTINE, FCB, ERRORRTN
where
ROUTINE is the name of the procedure to call. It
should set the Zero Flag if there is an error.
FCB is the name of the File Control Block.
ERRORRTN is the optional name of an error procedure
which the program will call if the Zero Flag is set.